package com.molichuxing.gateway.bff.car.services.impl;

import com.alibaba.fastjson.JSONObject;
import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.EmailUtil;
import com.molichuxing.gateway.bff.car.convertor.Convert;
import com.molichuxing.gateway.bff.car.entity.request.modify.YearlyInspectionModifyVo;
import com.molichuxing.gateway.bff.car.entity.response.CarYearlyInspectVo;
import com.molichuxing.gateway.bff.car.entity.response.YearlyInspectionLogVo;
import com.molichuxing.gateway.bff.car.entity.response.YearlyInspectionVo;
import com.molichuxing.gateway.bff.car.services.YearlyInspectBffService;
import com.molichuxing.gateway.utils.PoiExcelUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.request.create.MotRequestCreateDto;
import com.molichuxing.services.business.dto.response.*;
import com.molichuxing.services.business.service.*;
import com.molichuxing.services.infrastructure.dto.request.modify.YearlyInspectionModifyDto;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.dto.response.OwnershipDto;
import com.molichuxing.services.infrastructure.dto.response.StockStoreDto;
import com.molichuxing.services.infrastructure.dto.response.VehiclePictureDto;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.CarYearlyInspectStatusEnum;
import com.molichuxing.services.property.StockCarStockTypeEnum;
import com.molichuxing.services.property.YearlyInspectHandleStatusEnum;
import com.molichuxing.services.property.YearlyInspectHandleWayEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 车辆检验bff
 *
 * @author xuelin yi
 */
@Service("yearlyInspectBffService")
public class YearlyInspectBffServiceImpl implements YearlyInspectBffService {

    private static final Logger logger = LoggerFactory.getLogger(YearlyInspectBffServiceImpl.class);
    @Value("${email_account}")
    private String emailAccount;

    @Value("${email_password}")
    private String emailPassword;
    @Resource
    private YearlyInspectService yearlyInspectService;

    @Resource
    private CarYearlyInspectionBizService carYearlyInspectionBizService;

    @Resource
    private VehicleBizService vehicleBizService;

    @Resource
    private VehicleColorService vehicleColorService;
    @Resource
    private StockStoreService stockStoreService;

    @Resource
    private StockCarBizService stockCarBizService;

    @Resource
    private StoreBizService storeBizService;

    @Resource
    private VehiclePictureService vehiclePictureService;

    @Resource
    private OrderBizService orderBizService;

    @Resource
    private UserBizService userBizService;

    @Resource
    private OwnershipService ownershipService;

    @Resource
    private CarService carService;

    @Resource
    private MotBizService motBizService;

    @Override
    public Paged<CarYearlyInspectVo> getYearlyInspect(int yearlyInspectStatus, String licencePlate, String vin, Integer addressType, Integer addressId, String inspectStartDate, String inspectEndDate, Integer handleStatus, String sortName, String sortWay, Integer pageNum, Integer pageSize) {
        Integer stockId = null;
        if ((null != addressType) && (null != addressId)) {
            if (StockCarStockTypeEnum.STORE.getValue() == addressType) {
                StockStoreDto stockStoreDto = stockStoreService.getStockStoreByStoreId(addressId);
                if (stockStoreDto == null) {
                    stockId = -1;
                } else {
                    stockId = stockStoreDto.getStockId();
                }
            } else {
                stockId = addressId;
            }

        }
        if (null != inspectStartDate) {
            inspectStartDate = inspectStartDate + " 00:00:00";
        }
        if (null != inspectEndDate) {
            inspectEndDate = inspectEndDate + " 23:59:59";
        }
        Paged<CarYearlyInspectDto> page = carYearlyInspectionBizService.getYearlyInspect(CarYearlyInspectStatusEnum.getEnum(yearlyInspectStatus), licencePlate, vin, stockId, inspectStartDate, inspectEndDate, handleStatus, sortName, sortWay, pageNum, pageSize);
        Paged<CarYearlyInspectVo> result = Convert.toCarYearlyInspectPage(page);
        getCarYearlyInspectList(result.getList());
        getVehicleStock(result.getList());
        return result;
    }

    @Override
    public YearlyInspectionVo getYearlyInspectionByCarId(Integer carId) {
        YearlyInspectionBizDto yearlyInspectionBizDto = carYearlyInspectionBizService.getYearlyInspection(carId);
        String vehicleName = vehicleBizService.getVehicleName(yearlyInspectionBizDto.getVehicleId());
        String stockName = getStockName(carId);
        CarOrderBizDto carOrderBizDto = orderBizService.getUseOrderByCar(carId, null);
        UserBizDto userBizDto = null;
        if (carOrderBizDto != null) {
            Integer userId = carOrderBizDto.getUserId();
            userBizDto = userBizService.getUser(userId);
        }
        OwnershipDto ownershipDto = ownershipService.getOwnershipById(yearlyInspectionBizDto.getOwnershipId());
        return Convert.toYearlyInspectionVo(yearlyInspectionBizDto, vehicleName, stockName, userBizDto, ownershipDto);
    }

    @Override
    public Boolean modifyYearlyInspection(YearlyInspectionModifyVo modifyVo) throws Exception {
        Integer carId = modifyVo.getCarId();
        Integer handleWay = modifyVo.getHandleWay();
        Integer handleStatus = null;
        if (handleWay != null && YearlyInspectHandleWayEnum.THIRD_PARTY_HANDLE.getValue() == handleWay) {
            handleStatus = YearlyInspectHandleStatusEnum.IN_HANDLE.getValue();

            YearlyInspectionBizDto yearlyInspectionBizDto = carYearlyInspectionBizService.getYearlyInspection(carId);
            String insureProveUrl = yearlyInspectionBizDto.getInsureProveUrl();
            if(StringUtils.isBlank(insureProveUrl)){
                throw new BizException("请先上传车辆交强险保单后在办理年检");
            }
            OwnershipDto ownershipDto = ownershipService.getOwnershipById(yearlyInspectionBizDto.getOwnershipId());
            MotRequestCreateDto motRequestCreateDto = Convert.toMotRequestCreateDto(modifyVo, yearlyInspectionBizDto, ownershipDto);

            ResponseResult<Boolean> booleanResponseResult = motBizService.addMOT(motRequestCreateDto);
            if (null == booleanResponseResult || booleanResponseResult.getCode() != 0) {
                logger.info("年检异常，调用第三方服务异常");
                throw new BizException("年检异常");
            }
            Boolean resultBoolean = booleanResponseResult.getData();
            if (!resultBoolean) {
                logger.info("年检异常，调用第三方服务异常:" + JSONObject.toJSONString(booleanResponseResult));
                throw new BizException("年检异常");
            }
        } else if (handleWay != null && YearlyInspectHandleWayEnum.USER_HANDLE.getValue() == handleWay) {
            handleStatus = YearlyInspectHandleStatusEnum.HAVE_UPDATE.getValue();
        }

        YearlyInspectionModifyDto yearlyInspectionModifyDto = Convert.toYearlyInspectionModifyDto(modifyVo);
        yearlyInspectionModifyDto.setHandleStatus(handleStatus);
        return carYearlyInspectionBizService.modifyYearlyInspection(yearlyInspectionModifyDto);
    }

    @Override
    public List<YearlyInspectionLogVo> getYearlyInspectionLog(Integer carId) {
        List<YearlyInspectionLogBizDto> yearlyInspectionLogList = carYearlyInspectionBizService.getYearlyInspectionLogListByCarId(carId);
        return Convert.toYearlyInspectionLogVo(yearlyInspectionLogList);
    }

    private void getCarYearlyInspectList(List<CarYearlyInspectVo> carYearlyInspectList) {
        if ((null != carYearlyInspectList) && (carYearlyInspectList.size() != 0)) {
            for (CarYearlyInspectVo carYearlyInspectVo : carYearlyInspectList) {
                carYearlyInspectVo.setVehicleName(vehicleBizService.getVehicleName(carYearlyInspectVo.getVehicleId()));
            }
        }
    }

    private void getVehicleStock(List<CarYearlyInspectVo> carDtoList) {
        if (null != carDtoList && carDtoList.size() > 0) {
            List<Integer> ids = new ArrayList<>();
            List<Integer> vehicleIds = new ArrayList<>();
            for (CarYearlyInspectVo carDto : carDtoList) {
                vehicleIds.add(carDto.getVehicleId());
                ids.add(carDto.getCartId());
            }
            Map<Integer, StockCarBizDto> stockCarBizMap = stockCarBizService.getStockBaseCars(ids);

            for (CarYearlyInspectVo carDto : carDtoList) {
                StockCarBizDto stockCarBizDto = stockCarBizMap.get(carDto.getCartId());
                if (null != stockCarBizDto) {
                    if (stockCarBizDto.getStockType() == StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue()) {
                        carDto.setStockName(stockCarBizDto.getStockName());
                    } else {
                        try {
                            DealerStoreInfoBizDto dealerStoreInfoBizDto = storeBizService.getDealerStoreInfo(stockCarBizDto.getStoreId());
                            carDto.setStockName(dealerStoreInfoBizDto.getDealerShortName() + "-" + dealerStoreInfoBizDto.getStoreShortName());
                        } catch (Exception e) {
                            logger.error("查询门店信息异常");
                        }
                    }
                }
            }

            Map<Integer, List<VehiclePictureDto>> pictureMap = vehiclePictureService.getVehiclePictureByVehicleIds(vehicleIds);
            if (null != pictureMap) {
                for (CarYearlyInspectVo carDto : carDtoList) {
                    if (null != pictureMap.get(carDto.getVehicleId())) {
                        for (VehiclePictureDto vehiclePictureDto : pictureMap.get(carDto.getVehicleId())) {
                            if (vehiclePictureDto.getIsWhiteBg() && 1 == vehiclePictureDto.getPicDetailType()) {
                                carDto.setVehicleImg(vehiclePictureDto.getServerUrl());
                                break;
                            }

                        }
                    }
                }
            }
        }
    }

    private String getStockName(Integer carId) {
        StockCarBaseBizDto stockCarBaseBizDto = stockCarBizService.getStockBaseCar(carId);
        if (null == stockCarBaseBizDto) {
            return "";
        }
        if (stockCarBaseBizDto.getStockType() == StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue()) {
            return stockCarBaseBizDto.getStockName();
        } else {
            try {
                DealerStoreInfoBizDto dealerStoreInfoBizDto = storeBizService.getDealerStoreInfo(stockCarBaseBizDto.getStoreId());
                return dealerStoreInfoBizDto.getDealerShortName() + "-" + dealerStoreInfoBizDto.getStoreShortName();
            } catch (Exception e) {
                logger.error("查询门店信息异常");
                return "";
            }
        }
    }

    /**
     * 年检导出
     *
     * @param yearlyInspectStatus
     * @param licencePlate
     * @param vin
     * @param addressType
     * @param addressId
     * @param inspectStartDate
     * @param inspectEndDate
     * @return
     */
    @Override
    public List<CarYearlyInspectVo> getYearlyInspectDownload(String idList, int yearlyInspectStatus, String licencePlate, String vin, Integer addressType, Integer addressId, String inspectStartDate, String inspectEndDate) throws Exception {
        Integer stockId = null;
        if ((null != addressType) && (null != addressId)) {
            if (StockCarStockTypeEnum.STORE.getValue() == addressType) {
                StockStoreDto stockStoreDto = stockStoreService.getStockStoreByStoreId(addressId);
                if (stockStoreDto == null) {
                    stockId = -1;
                } else {
                    stockId = stockStoreDto.getStockId();
                }
            } else {
                stockId = addressId;
            }

        }

        if (null != inspectStartDate) {
            inspectStartDate = inspectStartDate + " 00:00:00";
        }
        if (null != inspectEndDate) {
            inspectEndDate = inspectEndDate + " 23:59:59";
        }
        List<String> inspectionIdList = null;
        if (StringUtils.isNoneBlank(idList)) {
            inspectionIdList = Arrays.asList(idList.split(","));
        }
        List<CarYearlyInspectDto> list = carYearlyInspectionBizService.getYearlyInspectDownload(inspectionIdList, CarYearlyInspectStatusEnum.getEnum(yearlyInspectStatus), licencePlate, vin, stockId, inspectStartDate, inspectEndDate);
        List<CarYearlyInspectVo> result = Convert.toCarYearlyInspectPage(list);

        getCarStock(result);
        return result;
    }

    @Override
    public long getYearlyInspectDownloadCount(String idList, int yearlyInspectStatus, String licencePlate, String vin, Integer addressType, Integer addressId, String inspectStartDate, String inspectEndDate) throws Exception {
        Integer stockId = null;
        if ((null != addressType) && (null != addressId)) {
            if (StockCarStockTypeEnum.STORE.getValue() == addressType) {
                StockStoreDto stockStoreDto = stockStoreService.getStockStoreByStoreId(addressId);
                if (stockStoreDto == null) {
                    stockId = -1;
                } else {
                    stockId = stockStoreDto.getStockId();
                }
            } else {
                stockId = addressId;
            }

        }

        if (null != inspectStartDate) {
            inspectStartDate = inspectStartDate + " 00:00:00";
        }
        if (null != inspectEndDate) {
            inspectEndDate = inspectEndDate + " 23:59:59";
        }
        List<String> inspectionIdList = null;
        if (StringUtils.isNoneBlank(idList)) {
            inspectionIdList = Arrays.asList(idList.split(","));
        }
        return carYearlyInspectionBizService.getYearlyInspectDownloadCount(inspectionIdList, CarYearlyInspectStatusEnum.getEnum(yearlyInspectStatus), licencePlate, vin, stockId, inspectStartDate, inspectEndDate);
    }

    private void getCarStock(List<CarYearlyInspectVo> carDtoList) throws Exception {
        if (null != carDtoList && carDtoList.size() > 0) {
            List<Integer> ids = carDtoList.stream().map(CarYearlyInspectVo::getCartId).collect(Collectors.toList());
            Map<Integer, StockCarBizDto> stockCarBizMap = stockCarBizService.getStockBaseCars(ids);

            List<Integer> storeIdList = null;
            if (stockCarBizMap != null && stockCarBizMap.size() > 0) {
                storeIdList = stockCarBizMap.values().stream().map(StockCarBizDto::getStoreId).collect(Collectors.toList());
            }
            Map<Integer, DealerStoreInfoBizDto> dealerStoreInfoMap = storeBizService.getDealerStoreInfoMap(storeIdList);
            Map<Integer, String> carNameMap = getCarName(carDtoList);

            for (CarYearlyInspectVo carDto : carDtoList) {
                if (carNameMap != null && carNameMap.size() > 0) {
                    Integer vehicleId = carDto.getVehicleId();
                    String cehicleName = carNameMap.get(vehicleId);
                    carDto.setVehicleName(cehicleName);
                }

                if (stockCarBizMap != null && stockCarBizMap.size() > 0) {
                    StockCarBizDto stockCarBizDto = stockCarBizMap.get(carDto.getId());
                    if (null == stockCarBizDto) {
                        continue;
                    }
                    if (stockCarBizDto.getStockType() == StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue()) {
                        carDto.setStockName(stockCarBizDto.getStockName());
                    } else {
                        if (dealerStoreInfoMap != null && dealerStoreInfoMap.size() > 0) {
                            DealerStoreInfoBizDto dealerStoreInfoBizDto = dealerStoreInfoMap.get(stockCarBizDto.getStoreId());
                            if (dealerStoreInfoBizDto != null) {
                                carDto.setStockName(dealerStoreInfoBizDto.getDealerShortName() + "-" + dealerStoreInfoBizDto.getStoreShortName());
                            }
                        }
                    }
                }
            }
        }
    }

    private Map<Integer, String> getCarName(List<CarYearlyInspectVo> carDtoList) {
        Map<Integer, String> result = null;
        if (null != carDtoList && carDtoList.size() > 0) {
            Set<Integer> ids = new HashSet<>();
            for (CarYearlyInspectVo carYearlyInspectVo : carDtoList) {
                ids.add(carYearlyInspectVo.getVehicleId());
            }
            List<Integer> vehicleIds = new ArrayList<>(ids);
            result = vehicleBizService.getVehicleFullName(vehicleIds);
        }
        return result;
    }

    /**
     * 年检导出
     *
     * @param inspectionIdList
     * @param yearlyInspectStatus
     * @param licencePlate
     * @param vin
     * @param addressType
     * @param addressId
     * @param inspectStartDate
     * @param inspectEndDate
     * @param user
     * @return
     * @throws Exception
     */
    @Async
    @Override
    public Boolean getYearlyInspectDownloadEmail(String inspectionIdList, int yearlyInspectStatus, String licencePlate, String vin, Integer addressType, Integer addressId, String inspectStartDate, String inspectEndDate,
                                                 UserEntity user) throws Exception {
        List<CarYearlyInspectVo> yearlyInspectDownload = getYearlyInspectDownload(inspectionIdList, yearlyInspectStatus, licencePlate, vin, addressType, addressId, inspectStartDate, inspectEndDate);
        String fileName = "年检列表(" + DateUtil.formatDate(LocalDate.now()) + ").xlsx";
        // 生成excel
        SXSSFWorkbook sxssBook = PoiExcelUtil.getYearlyInspectDownload(yearlyInspectDownload);
        // 发送邮件
        EmailUtil.sendMail(emailAccount, emailPassword, "年检列表数据", "年检列表数据", user.getAccount(), fileName, sxssBook);
        return true;
    }

}
